package com.lagou.filter;

import org.apache.dubbo.common.constants.CommonConstants;
import org.apache.dubbo.common.extension.Activate;
import org.apache.dubbo.rpc.*;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


@Activate(group = {CommonConstants.CONSUMER})
public class TPMonitorFilter implements Filter {
    public static Map<String, List<Long>> responseTimeMap = new ConcurrentHashMap<String, List<Long>>();
    static {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
        executor.scheduleAtFixedRate(new Runnable() {
            public void run() {
                System.out.println("scheduled "+responseTimeMap.keySet());
                for(String key:responseTimeMap.keySet()){
                    List<Long> responseTimeList = responseTimeMap.get(key);
                    Collections.sort(responseTimeList);
                    int tp90Size = (int)(responseTimeList.size()*0.9);
                    int tp95Size = (int)(responseTimeList.size()*0.95);
                    System.out.println(key+" recent 5s invocation TP90 :" + responseTimeList.get(tp90Size) + "毫秒");
                    System.out.println(key+" recent 5s invocation TP95 :" + responseTimeList.get(tp95Size) + "毫秒");
                    responseTimeMap.remove(key);
                }
            }
        }, 3, 5, TimeUnit.SECONDS);
    }
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        String methodName = invocation.getMethodName();
        List<Long> responseTimeList = responseTimeMap.get(methodName);
        if(responseTimeList==null){
            responseTimeList = new LinkedList<Long>();
        }
        long startTime = System.currentTimeMillis();
        try {
            // 执行方法
            return invoker.invoke(invocation);
        } finally {
            long responseTime = System.currentTimeMillis()-startTime;
            responseTimeList.add(responseTime);
            responseTimeMap.put(methodName,responseTimeList);
//                System.out.println("invoke time:"+responseTime + "毫秒");
        }
    }
}
